		include	Common.asm

BaseTick	equ	1193180

NoteEnd		equ	100
NoteRest	equ	101

; ==========================================================
DataSeg		segment para public 'data'

	FreqTable	dw BaseTick/262
			dw BaseTick/277
			dw BaseTick/294
			dw BaseTick/311
			dw BaseTick/330
			dw BaseTick/349
			dw BaseTick/370
			dw BaseTick/392
			dw BaseTick/415
			dw BaseTick/440
			dw BaseTick/466
			dw BaseTick/494

			dw BaseTick/523
			dw BaseTick/554
			dw BaseTick/587
			dw BaseTick/622
			dw BaseTick/659
			dw BaseTick/698
			dw BaseTick/740
			dw BaseTick/784
			dw BaseTick/831
			dw BaseTick/880
			dw BaseTick/932
			dw BaseTick/988

	MusicData	dw NoteRest, 4, 16, 4, NoteRest, 4, 15, 4
			dw 16, 4, 15, 4, 16, 4, 12, 4
			dw 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 4, 4, NoteRest, 4, 9, 4
			dw 11, 4, 11, 4, 11, 4, 11, 4, 11, 4, 4, 4, NoteRest, 4, 11, 4
			dw 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4
			dw NoteRest, 4, 16, 4, NoteRest, 4, 15, 4
			dw 16, 4, 15, 4, 16, 4, 12, 4
			dw 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 4, 4, NoteRest, 4, 9, 4
			dw 11, 4, 11, 4, 11, 4, 11, 4, 11, 4, 12, 4, 12, 4, 11, 4
			dw 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4
			dw NoteRest, 4, 11, 4, 11, 4, 12, 4, 12, 4, 14, 4, 14, 4
			dw 16, 4, 16, 4, 16, 4, 16, 4, 16, 4, 16, 4, 17, 4, 16, 4
			dw 14, 4, 14, 4, 14, 4, 14, 4, 14, 4, 14, 4, 16, 4, 14, 4
			dw 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 14, 4, 12, 4
			dw 11, 4, 16, 4, NoteRest, 4, 15, 4
			dw 16, 4, 15, 4, 16, 4, 12, 4
			dw 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 4, 4, NoteRest, 4, 9, 4
			dw 11, 4, 11, 4, 11, 4, 11, 4, 11, 4, 4, 4, NoteRest, 4, 11, 4
			dw 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4, 12, 4
			dw NoteRest, 4, 16, 4, NoteRest, 4, 15, 4
			dw 16, 4, 15, 4, 16, 4, 12, 4
			dw 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 4, 4, NoteRest, 4, 9, 4
			dw 11, 4, 11, 4, 11, 4, 11, 4, 11, 4, 12, 4, 12, 4, 11, 4, 9, 4, 9, 4, 9, 4
			dw 12, 4, 12, 4, 14, 4, 12, 4, 11, 4
			dw 9, 4, 9, 4, 9, 4, NoteRest, 4, 9, 4, 9, 4, 9, 4, 9, 4
			dw NoteRest, 4, NoteRest, 4, NoteRest, 4, NoteRest, 4
			dw NoteEnd, 0

	LastSoundTick	dw 0
	CurrLen		dw 0
	NoteLen		dw 0
	BeforeFreq	dw 0
	MusicPtr	NearPtr 0
	SoundPtr	NearPtr 0
	SoundLoop	db 1

DataSeg		ends

; ==========================================================
CodeSeg		segment para public 'code'
        assume  ds: DataSeg

; ----------------------------------------------------------
; PlayMusic - Plays music
; ----------------------------------------------------------
; Input:
;	bx	Music Data
; Output:	none
; ----------------------------------------------------------
PlayMusic	proc

	call	SoundOff

	mov	SoundPtr, bx
	mov	MusicPtr, bx

	ret

PlayMusic	endp


; ----------------------------------------------------------
; StopMusic - Plays music
; ----------------------------------------------------------
; Input:
;	bx	Music Data
; Output:	none
; ----------------------------------------------------------
StopMusic	proc

	push	bx

	mov	bx, 0
	call	PlayMusic

	pop	bx
	ret

StopMusic	endp


; ----------------------------------------------------------
; SoundOn - Turns on PC speaker
; ----------------------------------------------------------
; Input:
;	bx	frequency
; Output:	none
; ----------------------------------------------------------
SoundOn		proc

	push	ax

	mov	al, 0b6h		; control word
	out	43h, al

	mov	al, bl
	out	42h, al			; send freq (low byte)
	mov	al, bh
	out	42h, al			; send freq (high byte)

	or	al, 03h			; turn on the speaker
	out	61h, al

	pop	ax

	ret

SoundOn		endp


; ----------------------------------------------------------
; SoundOff - Turns off PC speaker
; ----------------------------------------------------------
; Input:	none
; Output:	none
; ----------------------------------------------------------
SoundOff	proc

	push	ax

	or	al, 0fch		; turn off the speaker
	out	61h, al

	pop	ax
	
	ret

SoundOff	endp


; ----------------------------------------------------------
; ProcessSound - Processes Sound
; ----------------------------------------------------------
; Input:	none
; Output:	none
; ----------------------------------------------------------
ProcessSound		proc

	push	ax
	push	bx
	push	cx

	call	GetClockTick

	mov	ax, dx
	sub	ax, LastSoundTick
	mov	LastSoundTick, dx

	cmp	ax, 1
	jb	SkipProcess

	cmp	SoundPtr, 0
	je	SkipProcess

	inc	CurrLen
	mov	ax, CurrLen
	cmp	ax, NoteLen
	jle	KeepSound

	mov	bx, SoundPtr
	add	SoundPtr, 2
	mov	bx, [bx]
	cmp	bx, NoteEnd
	jne	SoundNotEnd

	mov	bx, MusicPtr
	mov	SoundPtr, bx
	jmp	SkipProcess

SoundNotEnd:
	cmp	bx, NoteRest
	je	Rest

	shl	bx, 1
	add	bx, offset FreqTable
	mov	bx, [bx]
	
	cmp	bx, BeforeFreq
	je	SoundDone

	call	SoundOn
	mov	BeforeFreq, bx
	jmp	SoundDone

Rest:
	call	SoundOff

SoundDone:
	mov	bx, SoundPtr
	add	SoundPtr, 2
	mov	bx, [bx]
	mov	NoteLen, bx
	mov	CurrLen, 0
	jmp	SkipProcess

KeepSound:
	inc	CurrLen

SkipProcess:
	pop	cx
	pop	bx
	pop	ax
	ret

ProcessSound	endp

	
CodeSeg		ends

		end

